package com.withyou.design_pattern.proxyPatteren;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import com.withyou.design_pattern.proxyPatteren.StaticProxyPatteren.Target;

/**
 * 通过CGLIB 实现动态代理
 *
 * CGLIB 相比静态、JDK 动态代理  需要目标对象实现接口
 * 以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理
 * Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
 * 
 * Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.
 * 
 * Cglib子类代理实现方法:
   1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
   2.引入功能包后,就可以在内存中动态构建子类
   3.代理的类不能为final,否则报错
   4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
 */
public class CglibProxyPatteren {

	static class ProxyFactory implements MethodInterceptor{

		//维护目标对象
	    private Object target;

	    public ProxyFactory(Object target) {
	        this.target = target;
	    }

	    //给目标对象创建一个代理对象
	    public Object getProxyInstance(){
	        //1.工具类
	        Enhancer en = new Enhancer();
	        //2.设置父类
	        en.setSuperclass(target.getClass());
	        //3.设置回调函数
	        en.setCallback(this);
	        //4.创建子类(代理对象)
	        return en.create();
	    }
	    
		/**
		 * 方法拦截
		 */
		public Object intercept(Object obj, Method method, Object[] args,
				MethodProxy arg3) throws Throwable {
				System.out.println("开始老师先说开场白0");
	            //执行目标对象方法
	            Object returnValue = method.invoke(target, args);
				System.out.println("结束老师总结0");
		        return returnValue;
		}
	}
	
	
	public static void main(String[] args) {
		Target ta = new Target("test", 21);
		CglibProxyPatteren.ProxyFactory fa = new CglibProxyPatteren.ProxyFactory(ta);
		Target tProxy = (Target) fa.getProxyInstance();
		tProxy.say();
	}
}
